#include "KmyResourceManager.h"
#include "ResPath/ResourcePath.h"
#include "ResPath/ResPathImage.h"
#include "ResPath/ResPathScript.h"
#include "ResPath/ResPathSound.h"
#include "ResPath/ResPathSprite.h"
#include "ResPath/ResPathFont.h"
#include "KmyStream.h"

KmyResourceManager::KmyResourceManager()
{
    font = NULL;
}

KmyResourceManager::~KmyResourceManager(){
    clear();
    delete filemanager;
}

void KmyResourceManager::setFilemanager(KmyIFile *filemanager){
    this->filemanager = filemanager;
}

void KmyResourceManager::initialize(KmyConfig &config){
    res_list.clear();
    if (config.resource_list_path!=NULL && !config.resource_list_path->empty()){
        this->filemanager->fileOpen(*config.resource_list_path);
        int fsize = this->filemanager->getFileSize(*config.resource_list_path);
        u8* data = new u8[fsize];
        this->filemanager->read(*config.resource_list_path, data, fsize);
        KmyStream stm(data, fsize);
        string line = stm.readLine();
        while (!line.empty()){
            ResourcePath* rp = ResourcePath::createResPath(line);
            if (rp!=NULL){
                this->putResPath(rp);
            }
            line = stm.readLine();
        }
    }
    this->macro_script = NULL;
    if (config.macro_file_name!=NULL && !config.macro_file_name->empty()){
        // 初始化宏脚本
        this->macro_script = getScript(*config.macro_file_name);
    }
    this->entrance_script = NULL;
    if (config.entrance_script_name!=NULL && !config.entrance_script_name->empty()){
        // 初始化入口脚本
        this->entrance_script = getScript(*config.entrance_script_name);
    }
    if (config.font_name!=NULL && !config.font_name->empty()){
        if (this->font!=NULL){
            if (this->font->name != *config.font_name){
                delete font;
                font = loadFont(*config.font_name);
            }
        }else{
            font = loadFont(*config.font_name);
        }
    }
}

void KmyResourceManager::clear(){
    clearImage();
    clearSound();
    clearScript();
    clearText();
    clearSprite();
}

void KmyResourceManager::clearImage(){
    if (!img_resources.empty()){
        map<string, KmyImagePak*>::iterator iter = img_resources.begin();
        for (; iter != img_resources.end(); iter++){
            KmyImagePak *p=iter->second;
            p->finalize();
            delete p;
        }
        img_resources.clear();
    }
}

void KmyResourceManager::clearSound(){

}

void KmyResourceManager::clearScript(){
    if (!scp_resources.empty()){
        map<string, KmyScript*>::iterator iter = scp_resources.begin();
        for (; iter != scp_resources.end(); iter++){
            KmyScript *p=iter->second;
            p->finalize();
            delete p;
        }
        img_resources.clear();
    }
}

void KmyResourceManager::clearText(){

}

void KmyResourceManager::clearSprite(){
    if (!spt_resources.empty()){
        map<string, KmySpriteTemplate*>::iterator iter = spt_resources.begin();
        for (; iter != spt_resources.end(); iter++){
            KmySpriteTemplate *p=iter->second;
            p->finalize();
            delete p;
        }
        img_resources.clear();
    }
}

KmyResourceManager* KmyResourceManager::instance = NULL;

KmyResourceManager* KmyResourceManager::getInstance()
{
    if (instance!=NULL){
        return instance;
    }else{
        instance = new KmyResourceManager();
        return instance;
    }
}

bool KmyResourceManager::putResPath(ResourcePath *rp){
    pair<map<string,ResourcePath*>::iterator,bool> ret;
    ret = res_list.insert(pair<string, ResourcePath*>(rp->res_name, rp));
    return ret.second;
}

ResourcePath* KmyResourceManager::getResPath(const string &resname){
    map<string, ResourcePath*>::iterator iter = res_list.find(resname);
    if (iter!=res_list.end()){
        return iter->second;
    }
    return NULL;
}

void KmyResourceManager::resListClear(){
    if (!res_list.empty()){
        map<string, ResourcePath*>::iterator iter = res_list.begin();
        for (; iter!=res_list.end(); iter++){
            delete iter->second;
        }
        res_list.clear();
    }
}

KmyImagePak* KmyResourceManager::getImage(const string &name){
    map<string, KmyImagePak*>::iterator iter = img_resources.find(name);
    if (iter!=img_resources.end()){
        return iter->second;
    }
    ResPathImage *rp_img = (ResPathImage*)getResPath(name);
    if (rp_img==NULL){
        return NULL;
    }
    KmyImagePak* imgpak = filemanager->readImagePak(rp_img);
    if (imgpak!=NULL){
        putImage(name, imgpak);
    }
    return imgpak;
}

bool KmyResourceManager::putImage(const string &name, KmyImagePak *imgs){
    pair<map<string, KmyImagePak*>::iterator,bool> ret;
    ret = img_resources.insert(pair<string, KmyImagePak*>(name, imgs));
    return ret.second;
}

KmyScript* KmyResourceManager::getScript(const string &name){
    map<string, KmyScript*>::iterator iter = scp_resources.find(name);
    if (iter!=scp_resources.end()){
        return iter->second;
    }
    ResPathScript *rp_scp = (ResPathScript*)getResPath(name);
    if (rp_scp==NULL){
        return NULL;
    }
    KmyScript* scp = filemanager->readScript(rp_scp);
    if (scp!=NULL){
        if (putScript(name, scp)){
            return scp;
        }else{
            scp->finalize();
            delete scp;
        }
    }
    return scp;
}

bool KmyResourceManager::putScript(const string &name, KmyScript* scp){
    pair<map<string,KmyScript*>::iterator,bool> ret;
    ret = scp_resources.insert(pair<string, KmyScript*>(name, scp));
    return ret.second;
}

KmySpriteTemplate *KmyResourceManager::getSpriteTemplate(const string &name){
    map<string, KmySpriteTemplate*>::iterator iter = spt_resources.find(name);
    if (iter!=spt_resources.end()){
        return iter->second;
    }
    ResPathSprite *rp_spt = (ResPathSprite*)getResPath(name);
    if (rp_spt==NULL){
        return NULL;
    }
    KmySpriteTemplate* spt = filemanager->readSprite(rp_spt);
    if (spt!=NULL){
        if (putSprite(name, spt)){
           return spt;
        }else{
            spt->finalize();
            delete spt;
        }
    }
    return NULL;
}

bool KmyResourceManager::putSprite(const string &name, KmySpriteTemplate *spt){
    pair<map<string, KmySpriteTemplate*>::iterator,bool> ret;
    ret = spt_resources.insert(pair<string, KmySpriteTemplate*>(name, spt));
    return ret.second;
}

KmyScript* KmyResourceManager::getEntranceScript(){
    return this->entrance_script;
}

KmyScript* KmyResourceManager::getMacroScript(){
    return this->macro_script;
}

KmyFont* KmyResourceManager::getFont(){
    return font;
}

KmyFont* KmyResourceManager::loadFont(const string &name){
    ResPathFont *rp_f = (ResPathFont*)getResPath(name);
    if (rp_f==NULL){
        return NULL;
    }
    KmyFont* f = filemanager->readFont(rp_f);
    return f;
}

//KmyITexture* KmyResourceManager::createTexture(const string &name,
//                                               int mode, const u8 *data, int w, int h, bool is_buffer){
//    return filemanager->createTexture(name, mode,
//                                      data, w, h, is_buffer);
//}
